<template>
  <div class="editor" v-loading="initializing">
    <div class="editor-page" v-if="currPage">
      <el-collapse v-model="collapseName" accordion>
        <el-collapse-item name="page">
          <template #title>
            <div class="page-title">
              <div class="page-title-name">页面配置</div>
              <el-dropdown trigger="hover" placement="bottom-start">
                <el-button @click.stop text class="page-title-icon">
                  <ac-icon iconId="018dc9c3efed46e8b927"></ac-icon>
                </el-button>
                <template #dropdown>
                  <el-dropdown-menu>
                    <el-dropdown-item @click="addPage({type: '2'})">
                      <ac-icon iconId="018dc9c3efed46e8b927" color="#21D914FF" style="margin-right: 5px" />新增页面
                    </el-dropdown-item>
                    <el-dropdown-item @click="addPage({type: '1'})">
                      <ac-icon iconId="018dc9c3efedbb59d0b3" color="orange" style="margin-right: 5px" />新增目录
                    </el-dropdown-item>
                  </el-dropdown-menu>
                </template>
              </el-dropdown>
            </div>
          </template>
          <div class="filter-box">
            <el-input placeholder="搜索" v-model="filterText" clearable />
          </div>
          <el-tree
            ref="tree"
            class="tree"
            node-key="id"
            v-loading="treeLoading"
            element-loading-text="数据加载中..."
            draggable
            default-expand-all
            :data="treeData"
            :props="treeProps"
            :highlight-current="true"
            :filter-node-method="filterNode"
            :show-checkbox="treeCheck"
            @node-click="pageNodeClick"
            @node-drop="pageNodeDrop"
          >
            <template v-slot="{ node, data }">
              <div class="node-item">
                <ac-icon v-if="data.type === '1' && node.expanded" color="orange" iconId="018dc9c3efedbb59d0b3" />
                <ac-icon v-else-if="data.type === '1'" color="orange" iconId="018dc9c3efed6d208a59" />
                <ac-icon
                  v-else-if="data.type === '2' && mobile.homeId === data.id"
                  title="首页"
                  color="#117fe8"
                  iconId="018ece4f71a419d2a433"
                />
                <ac-icon
                  v-else-if="data.type === '2' && mobile.loginId === data.id"
                  title="登录页"
                  color="#117fe8"
                  iconId="018dca444e0754edef13"
                />
                <ac-icon
                  v-else-if="data.type === '2'"
                  color="#117fe8"
                  iconId="018dc9c3efb74ac607cb"
                />
                <div class="node-label" :title="data.text + (data.data.title ? '（' + data.data.title + '）' : '')">
                  <div class="item-name">
                    <span>{{data.text + (data.data.title ? '（' + data.data.title + '）' : '')}}</span>
                  </div>
                </div>
                <div class="node-button">
                  <el-dropdown trigger="hover" placement="bottom-start">
                    <span class="node-button-item">
                      <ac-icon iconId="018dca6283a1e534a046" @click.stop />
                    </span>
                    <template #dropdown>
                      <el-dropdown-menu v-if="data.type === '1'">
                        <el-dropdown-item @click="addPage({id: data.data.id, type: '2'})">
                          <ac-icon iconId="018dc9c3efed46e8b927" color="#21D914FF" style="margin-right: 5px" />新增页面
                        </el-dropdown-item>
                        <el-dropdown-item @click="addPage({id: data.data.id, type: '1'})">
                          <ac-icon iconId="018dc9c3efedbb59d0b3" color="orange" style="margin-right: 5px" />新增目录
                        </el-dropdown-item>
                        <el-dropdown-item @click="editPage(data.data)">
                          <ac-icon iconId="018dca6db20c6a3aaf68" color="#0085f6" style="margin-right: 5px" />编辑目录
                        </el-dropdown-item>
                        <el-dropdown-item @click="deletePage(data.data)">
                          <ac-icon iconId="018dc9c3efd3a0502886" color="#F56C6C" style="margin-right: 5px" />删除目录
                        </el-dropdown-item>
                      </el-dropdown-menu>
                      <el-dropdown-menu v-else-if="data.type === '2'">
                        <el-dropdown-item @click="copyPage(data.data)">
                          <ac-icon iconId="018dc9c3efb82f31c161" color="#21D914FF" style="margin-right: 5px" />复制页面
                        </el-dropdown-item>
                        <el-dropdown-item @click="editPage(data.data)">
                          <ac-icon iconId="018dca6db20c6a3aaf68" color="#0085f6" style="margin-right: 5px" />编辑页面
                        </el-dropdown-item>
                        <el-dropdown-item @click="homePage(data.data)">
                          <ac-icon iconId="018ece4f71a419d2a433" color="orange" style="margin-right: 5px" />设为首页
                        </el-dropdown-item>
                        <el-dropdown-item @click="loginPage(data.data)">
                          <ac-icon iconId="018dca444e0754edef13" color="orange" style="margin-right: 5px" />设为登录页
                        </el-dropdown-item>
                        <el-dropdown-item @click="deletePage(data.data)">
                          <ac-icon iconId="018dc9c3efd3a0502886" color="#F56C6C" style="margin-right: 5px" />删除页面
                        </el-dropdown-item>
                      </el-dropdown-menu>
                    </template>
                  </el-dropdown>
                </div>
              </div>
            </template>
          </el-tree>
        </el-collapse-item>
      </el-collapse>
    </div>
    <div class="editor-container" v-if="activatedNode">
      <div class="editor-main" :style="{backgroundImage: 'url(' + mobileBg + ')'}">
        <div class="mobile-title">{{ currPage ? (currPage.title || mobile.title) : mobile.title}}</div>
        <draggable
          v-if="!loading"
          v-model="rootNode"
          :id="rootNode.id"
          class="draggable-page"
          :style="visual.parseStyle(rootNode.currStyle, {overflow: 'auto'})"
          @click.stop="activeNode(rootNode)"
          @mouseoverNode="mouseoverNode"
          @activeNode="activeNode"
          @deleteNode="deleteNode"
        />
        <div
          v-if="tipsNodeTree.length > 0"
          class="active-box"
          :style="tipsBoxStyle"
        >
          <div class="tips-box">
            <div class="tips-operate">
              <div class="tips-name" @click="showTipsInput">
                <span
                  v-if="!tipsBoxEdit"
                  class="tips-name-txt"
                >{{activatedNode.name}}</span>
                <el-input
                  v-else
                  ref="tipsBoxInput"
                  v-model="activatedNode.name"
                  size="small"
                  @keyup.enter="tipsBoxEdit = false"
                  @blur="tipsBoxEdit = false"
                />
              </div>
              <div class="tips-copy" title="复制" @click="copyNode(activatedNode)">
                <ac-icon iconId="018dc9c3efb82f31c161" />
              </div>
              <div class="tips-tpl" title="保存到模板" @click="saveTplNode(activatedNode)">
                <ac-icon iconId="018ece4f68eaa77e4813" />
              </div>
              <div class="tips-delete" title="删除" @click="deleteNode(activatedNode)">
                <ac-icon iconId="018dc9c3efd3a0502886" />
              </div>
            </div>
            <div class="tips-node">
              <div
                v-for="(item, index) in tipsNodeTree"
                :key="index"
                @click="activeNode(item)"
                class="tips-node-item"
              >{{item.name}}</div>
            </div>
          </div>
        </div>
      </div>
    </div>
    <div class="editor-tool" v-if="currPage">
      <ac-visual-tool
        ref="visualTool"
        type="应用"
        :mobileId="mobileId"
        @preview="preview"
        @save="save"
        @quit="quit"
        @change="changeConfig"
        @activeNode="activeNode"
      />
    </div>

    <div class="mouseover-box" :style="moveBoxStyle">
      <div class="tips-box">{{moveBoxName}}</div>
    </div>
  </div>

  <!--页面预览-->
  <el-dialog
    v-model="previewVisible"
    title="预览"
    :close-on-click-modal="false"
    class="no-padding"
    append-to-body
    destroy-on-close
    fullscreen
    draggable
  >
    <div style="height: 100%;display: flex;flex-direction: column">
    </div>
  </el-dialog>

  <el-dialog
    v-model="pageVisible"
    :title="pageTitle"
    width="500px"
    :close-on-click-modal="false"
    destroy-on-close
    append-to-body
    draggable
  >
    <el-form
      ref="pageForm"
      label-width="100px"
      label-position="right"
      :model="pageData"
      :rules="pageRules"
    >
      <el-row>
        <el-col :span="24">
          <el-form-item label="名称" prop="name">
            <el-input v-model="pageData.name" auto-complete="off"></el-input>
          </el-form-item>
        </el-col>
      </el-row>
      <el-row v-if="pageData.type === '2'">
        <el-col :span="24">
          <el-form-item label="标题" prop="title">
            <el-input v-model="pageData.title" auto-complete="off"></el-input>
          </el-form-item>
        </el-col>
      </el-row>
    </el-form>
    <template #footer>
      <el-button
        size="default"
        type="info"
        @click="pageVisible=false"
      >取消</el-button>
      <el-button
        type="primary"
        size="default"
        :loading="pageLoading"
        @click="submitPageForm"
      >提交</el-button>
    </template>
  </el-dialog>
</template>

<script setup>
import { ref, onMounted, nextTick, provide, watch } from 'vue';
import { ElMessage, ElMessageBox } from "element-plus";
import AcVisualTool from "./tool.vue";
import visual from "@/visual/js/visual";
import tool from "@/utils/tool";
import Draggable from "@/admin/visual/draggable.vue";
import api from "@/http/api";
import mobileBg from "@/assets/images/mobile-bg.png";
import { useAdminVisualCompStore } from "@/admin/visual/js/visual-comp";
import { components } from "@/admin/visual/js/component.config";

const emit = defineEmits(['save', 'quit']);
const props = defineProps({
  id: String
});

const initializing = ref(true);
const compDataList = ref([]);
const visualComp = useAdminVisualCompStore();
const mobileId = ref(props.id || '');
const visualTool = ref();
const unSave = ref(false);
const rootNode = ref({inputParamList: []});
const activatedNode = ref({});
const loading = ref(false);
const tipsBoxStyle = ref('');
const tipsBoxInput = ref();
const tipsBoxEdit = ref(false);
const tipsNodeTree = ref([]);

const moveBoxName = ref('');
const moveBoxStyle = ref('');

const previewVisible = ref(false);
const pageParamList = ref([]);

const collapseName = ref('page');
const filterText = ref('');
const tree = ref();
const treeLoading = ref(false);
const treeData = ref([]);
const treeCheck = ref(false);
const treeProps = ref({
  children: 'children',
  label: 'text'
});

const mobile = ref({});
const currPage = ref(null);
const pageCache = ref({});
const nameIndex = ref([]);
provide('rootNode', rootNode);
provide('activatedNode', activatedNode);
provide('pageParamList', pageParamList);
provide('nameIndex', nameIndex);

const filterNode = (value, data) => {
  if (!value) return true;
  return data.text.indexOf(value) >= 0
    || (data.data.code != null && data.data.code.indexOf(value) >= 0);
};

const pageNodeClick = async(data) => {
  if (data.data.type !== '2') {
    if (currPage.value && currPage.value.id) {
      await nextTick(() => {
        tree.value.setCurrentKey(null);
        tree.value.setCurrentKey(currPage.value.id);
      });
    }
    return;
  }
  if (currPage.value && currPage.value.id === data.data.id) return true;

  loading.value = true;
  await initPageNode(data.data);
  await nextTick(() => loading.value = false);
  return true;
};

const pageNodeDrop = (node, inNode, position) => {
  const data = {
    id: node.data.id,
    parentId: position === 'inner' ? inNode.data.id : inNode.data.pid,
    beforeId: position === 'before' ? inNode.data.id : '',
    afterId: position === 'after' ? inNode.data.id : '',
  }
  api.post('/system/mobilePage/updatePosition', data).then(() => {
    loadPageData(currPage.value);
  });
};

const activeNode = async(node) => {
  activatedNode.value = node;
  tipsNodeTree.value = getAllParents(node.id, rootNode.value);
  await initNodeData(activatedNode.value);
};

const showTipsInput = () => {
  tipsBoxEdit.value = true;
  nextTick(() => {
    tipsBoxInput.value && tipsBoxInput.value.focus();
  });
};

const showTipsBox = () => {
  if (activatedNode.value && activatedNode.value.id && activatedNode.value.type !== 'page') {
    const element = document.getElementById(activatedNode.value.id);
    if (element) {
      const rect = element.getBoundingClientRect();
      tipsBoxStyle.value = `
        display: block;
        width: ${rect.width}px;
        height: ${rect.height}px;
        top: ${rect.top}px;
        left: ${rect.left}px;`;
    }
  } else {
    tipsBoxStyle.value = '';
  }
};

const copyNode = (node) => {
  const parentNode = getParentNode(node.id, rootNode.value);
  if (!parentNode) return;

  const idMap = {};
  const newNode = tool.deepClone(node);
  tool.walkProp(newNode, (key, obj) => {
    if (key === 'id') {
      const newId = tool.uuid();
      if (obj[key]) {
        idMap[obj[key]] = newId;
      }
      obj[key] = newId;
    } else if (key === 'name') {
      if (obj[key].indexOf("-") > 0) {
        const name = obj[key].replace(/\d+$/, '');
        obj[key] = getNodeName(name);
      }
    }
  });
  tool.walkProp(newNode, (key, obj) => {
    if (obj[key] && typeof obj[key] === 'string' && idMap[obj[key]]) {
      obj[key] = idMap[obj[key]];
    }
  });
  parentNode.children.push(newNode);
  activeNode(newNode);
};

const saveTplNode = (node) => {
  const json = JSON.stringify(node);
  api.post("/system/pageVisualTemplate/save",
    {type: '普通', name: node.name || '', json: json}
  ).then(res => {
    if (res.code === '1') {
      ElMessage.success("保存模板成功！");
      visualTool.value.loadVisualTpl();
    }
  });
};

const buildNameIndex = () => {
  const regex = new RegExp('-\\d+$');
  tool.walkTree(rootNode.value, node => {
    if (node.name && node.name.match(regex)) {
      const lastIndex = node.name.lastIndexOf('-');
      const name = node.name.substring(0, lastIndex);
      const maxIndex = parseInt(node.name.substring(lastIndex + 1));
      if (!nameIndex.value[name] || nameIndex.value[name] < maxIndex) {
        nameIndex.value[name] = maxIndex;
      }
    }
  });
};

const getNodeName = (name) => {
  if (!name) return '组件-01';

  if (name.endsWith('-')) {
    name = name.substr(0, name.length - 1);
  }

  if (!nameIndex.value[name]) {
    buildNameIndex();
  }

  if (!nameIndex.value[name]) {
    nameIndex.value[name] = 0;
  }

  let index = ++nameIndex.value[name];
  return name + '-' + (index < 10 ? '0' : '') + index;
};

const deleteNode = (node) => {
  if (typeof node === 'undefined' || node == null) {
    node = activatedNode.value;
  }

  let nodeName;
  if (!node.name) {
    nodeName = '此项'
  } else {
    nodeName = '【' + node.name + '】';
  }
  ElMessageBox.confirm('请确认是否删除' + nodeName + '？', '提示', {type: 'warning'}).then(() => {
    doDeleteNode(node, rootNode.value.children || []);
    tipsBoxStyle.value = '';
    activatedNode.value = {compData: {}};
  }).catch(()=>{});
};

const doDeleteNode = (node, list) => {
  if (typeof node === 'undefined' || node == null
    || typeof list === 'undefined' || list === null || list.length === 0) {
    return false;
  }

  for (let i=0; i<list.length; i++) {
    if (list[i].id === node.id) {
      list.splice(i, 1);
      return true;
    }

    if (doDeleteNode(node, list[i].children || [])) {
      return true;
    }
  }
};

const mouseoverNode = (item) => {
  if (!item) {
    moveBoxStyle.value = '';
    moveBoxName.value = '';
  } else {
    const element = document.getElementById(item.id);
    if (element) {
      const rect = element.getBoundingClientRect();
      moveBoxStyle.value = `
        display: block;
        width: ${rect.width}px;
        height: ${rect.height}px;
        top: ${rect.top}px;
        left: ${rect.left}px;`;
      moveBoxName.value = item.name;
    }
  }
};

const getAllParents = (nodeId, tree) => {
  const parents = [];

  function findParents(id, tree) {
    if (id === tree.id) {
      return true;
    }

    for (let children of tree.children || []) {
      if (findParents(id, children)) {
        if (tree.builtin !== true) {
          parents.push(tree);
        }
        return true;
      }
    }

    return false;
  }

  findParents(nodeId, tree);
  return parents;
};

const getParentNode = (nodeId, node) => {
  for (let children of node.children || []) {
    if (children.id === nodeId) {
      return node;
    }

    const parentNode = getParentNode(nodeId, children);
    if (parentNode != null) {
      return parentNode;
    }
  }

  return null;
};

const preview = () => {
  previewVisible.value = true;
};

const save = (manual) => {
  if (!manual) {
    if (unSave.value !== true) return;
    unSave.value = false;
  }

  const pageList = [];
  for (let pageId of Object.keys(pageCache.value)) {
    const page = pageCache.value[pageId];
    if (!manual && page.unSave !== true) continue;

    page.unSave = false;
    const data = tool.deepClone(page, prop => prop !== 'currStyle' && prop !== 'currCompStyle' && prop !== 'dataList');
    delete data['unSave'];
    pageList.push({id: pageId, jsonText: JSON.stringify(data)});
  }

  if (pageList.length === 0) return;

  api.post('/system/mobilePage/saveJsonList', pageList).then(res => {
    if (res.code === '1' && manual) {
      ElMessage.success(res.message);
    } else if (res.code !== '1') {
      ElMessage.error(res.message);
    }
  }).catch(e => {
    console.log(e);
  });
};

const quit = () => {
  if (unSave.value) {
    ElMessageBox.confirm('修改未保存是否退出？', '提示', {type: 'warning'}).then(() => {
      emit('quit');
    }).catch(() => {});
  } else {
    emit('quit');
  }
};

const changeConfig = () => {
  if (!initializing.value) {
    rootNode.value.unSave = true;
    unSave.value = true;
  }
};

const initPageNode = async(data) => {
  initializing.value = true;
  currPage.value = data;
  if (pageCache.value[currPage.value.id]) {
    rootNode.value = pageCache.value[currPage.value.id];
  } else {
    if (currPage.value.jsonText) {
      rootNode.value = JSON.parse(currPage.value.jsonText);
      if (!rootNode.value.currStyle
        && rootNode.value.styleList
        && rootNode.value.styleList.length > 0) {
        rootNode.value.currStyle = rootNode.value.styleList[0].style || {};
      }
      rootNode.value.compData.inputData = true;
    } else {
      rootNode.value = visual.createNode('页面', {type: 'page'});
      rootNode.value.compData.inputData = true;
    }

    pageCache.value[currPage.value.id] = rootNode.value;
  }

  await nextTick(() => {
    initializing.value = false;
    activeNode(rootNode.value);
  });
};

const initNodeData = async(node) => {
  const data = await getCompData(node.type) || {};
  node.compData.inputData = data.inputData || node.compData.inputData || false;
  if (!node.compData.dataJson) {
    node.compData.dataJson = JSON.stringify(data.dataList || []);
  }
  const fieldList = node.compData.fieldList || [];
  if (fieldList.length === 0) {
    (data.fieldList || '').split(',').forEach(fieldName => {
      if (fieldName) {
        fieldList.push({
          id: tool.uuids(),
          name: fieldName,
          value: fieldName,
          builtin: !!data.fieldBuiltIn
        });
      }
    });
  }
  node.compData.fieldList = fieldList;
};

const loadMobileData = async() => {
  if (!mobileId.value) {
    ElMessage.error("参数不正确！");
    window.close();
    return;
  }

  const res = await api.post('/system/mobile/queryBy', {id: mobileId.value});
  mobile.value = res.data;
};

const loadPageData = async(page) => {
  if (!mobileId.value) {
    ElMessage.error("参数不正确！");
    window.close();
    return;
  }

  treeLoading.value = true;
  const res = await api.post('/system/mobilePage/queryTree', {mobileId: mobileId.value});
  treeData.value = res.data.children;
  treeLoading.value = false;

  if (page && page.id === currPage.value.id) return;

  if (!page) {
    page = findFirstPage(treeData.value);
  }

  if (!page) {
    page = {};
  }

  if (page) {
    await initPageNode(page);
    tree.value.setCurrentKey(page.id);
  }
};

// const loadPageParam = async() => {
//   (rootNode.value.compData.fieldList || []).forEach(field => {
//     const find = pageParamList.value.find(param => param.id === field.id);
//     if (!find) {
//       pageParamList.value.push(field);
//     }
//   });
// };

const findFirstPage = (list) => {
  for (let child of list) {
    if (child.data.type === '2') {
      return child.data;
    } else {
      if (child.children) {
        const result = findFirstPage(child.children);
        if (result) return result.data;
      }
    }
  }
  return null;
};

const pageVisible = ref(false);
const pageTitle = ref('');
const pageForm = ref();
const pageData = ref({});
const pageLoading = ref(false);
const pageRules = ref({
  name: [
    {required: true, message: '名称不能为空！', trigger: 'blur'},
    {max: 50, message: '名称长度最多只能是50个字符', trigger: ['blur', 'change']}
  ],
  title: [
    {required: true, message: '标题不能为空！', trigger: 'blur'},
    {max: 50, message: '标题长度最多只能是50个字符', trigger: ['blur', 'change']}
  ]
});

const addPage = (data) => {
  pageData.value = {
    parentId: data ? data.id : '',
    type: data ? data.type : '2',
    mobileId: mobileId.value
  };
  pageTitle.value = "新增页面";
  pageLoading.value = false;
  pageVisible.value = true;
};

const editPage = (item) => {
  pageData.value = tool.deepClone(item);
  pageTitle.value = "编辑页面";
  pageLoading.value = false;
  pageVisible.value = true;
};

const copyPage = (data) => {
  api.post('/system/mobilePage/copy', {id: data.id}).then(res => {
    if(res.code === '1') {
      loadPageData(currPage.value);
      ElMessage.success(res.message);
    } else {
      ElMessage.error(res.message);
    }
  });
};

const homePage = (data) => {
  ElMessageBox.confirm('请确认是否将页面【' + data.name + '】设为首页？', '提示', {type: 'warning'}).then(() => {
    api.post('/system/mobile/updateHome', {id: mobileId.value, homeId: data.id}).then(res => {
      if (res.code === '1') {
        mobile.value.homeId = data.id;
        ElMessage.success(res.message);
      } else {
        ElMessage.error(res.message);
      }
    });
  });
};

const loginPage = (data) => {
  ElMessageBox.confirm('请确认是否将页面【' + data.name + '】设为登录页面？', '提示', {type: 'warning'}).then(() => {
    api.post('/system/mobile/updateLogin', {id: mobileId.value, loginId: data.id}).then(res => {
      if (res.code === '1') {
        mobile.value.loginId = data.id;
        ElMessage.success(res.message);
      } else {
        ElMessage.error(res.message);
      }
    });
  });
};

const deletePage = (data) => {
  if (!data || !data.id) return;

  ElMessageBox.confirm('请确认是否删除页面【' + data.name + '】？', '提示', {type: 'warning'}).then(() => {
    api.post('/system/mobilePage/delete', data).then(res => {
      if (res.code === '1') {
        loadPageData(data.id === currPage.value.id ? null : currPage.value);
        if (pageCache.value[data.id]) {
          delete pageCache.value[data.id];
        }
        ElMessage.success(res.message);
      } else {
        ElMessage.error(res.message);
      }
    });
  });
};

const submitPageForm = () => {
  pageForm.value.validate(valid => {
    if (valid) {
      ElMessageBox.confirm('请确认是否提交？', '提示', {type: 'info'}).then(() => {
        pageLoading.value = true;
        api.post('/system/mobilePage/save', pageData.value).then(res => {
          if(res.code === '1') {
            if (currPage.value && currPage.value.id === res.data.id) {
              currPage.value.name = res.data.name;
              currPage.value.title = res.data.title;
            }
            pageVisible.value = false;
            ElMessage.success(res.message);
            loadPageData(res.data);
          } else {
            ElMessage.error(res.message);
          }
          pageLoading.value = false;
        }).catch(() => {
          pageLoading.value = false;
        })
      });
    } else {
      ElMessage.error('数据录入不正确，请重新检查！');
    }
  });
};

const createCompData = (data, children) => {
  (children || []).forEach(item => {
    if (item.type && item.inputData) {
      data[item.type] = {
        inputData: item.inputData,
        fieldList: item.fieldList || '',
        fieldBuiltIn: !!item.fieldBuiltIn,
        dataList: item.dataList || []
      };
    }
    createCompData(data, item.children);
  });
};

const getCompData = async(type) => {
  if (type) {
    if (!compDataList.value[type]) {
      const comp = await visualComp.getVisualComp(type);
      compDataList.value[type] = comp || {};
    }
    return tool.deepClone(compDataList.value[type]);
  } else {
    return {};
  }
};

watch(() => filterText.value, val => {
  tree.value.filter(val);
});

watch(() => rootNode.value.compData?.inputParamList, (value) => {
  pageParamList.value = value || [];
}, {deep: true});

onMounted(async() => {
  initializing.value = true;
  await loadMobileData();
  await loadPageData();
  createCompData(compDataList.value, components);
  // await loadPageParam();
  setInterval(showTipsBox, 200);
  initializing.value = false;
});
</script>

<style scoped lang="scss">
.editor {
  height: 100%;
  display: flex;
  flex-direction: row;
  position: relative;
  background: #ffffff;
  .editor-container {
    flex-grow: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    overflow: auto;
    background-color: #f0f2f5;
    .editor-main {
      flex-shrink: 0;
      display: block;
      width: 386px;
      height: 782px;
      padding: 50px 13px;
      margin: auto;
      box-sizing: border-box;
      background-size: cover;
      .mobile-title {
        height: 44px;
        line-height: 44px;
        text-align: center;
        font-size: 16px;
        font-weight: bold;
        background-color: rgb(248, 248, 248);
        color: rgb(0, 0, 0);
      }
    }
    .draggable-page {
      width: 100%;
      height: calc(100% - 44px);
      box-sizing: border-box;
      background: white;
      overflow: auto;
      font-family: "Microsoft YaHei", "Helvetica Neue", Helvetica, "PingFang SC", "Hiragino Sans GB", Arial, sans-serif;
      :deep(.empty) {
        width: 100%;
        height: 100px;
        box-sizing: border-box;
        box-shadow: inset 0 0 20px rgba(0, 0, 0, 0.3);
        outline: 1px dashed #333 !important;
        outline-offset: -2px !important;
      }
    }
    .draggable-page::-webkit-scrollbar {
      display: none;
    }
    .draggable-page:after {
      content: '';
      height: 50px;
      display: block;
    }
  }
  .editor-tool {
    z-index: 100;
    width: 370px;
    flex-shrink: 0;
  }
}
.active-box {
  display: none;
  position: absolute;
  border: 1px solid #0085f6;
  box-sizing: border-box;
  pointer-events: none;
  .tips-box {
    position: relative;
    top: calc(100% + 3px);
    pointer-events: auto;
    display: flex;
    flex-direction: column;
    width: fit-content;
    .tips-operate {
      display: inline-flex;
      flex-direction: row;
      align-items: center;
      .tips-name, .tips-copy, .tips-tpl, .tips-delete {
        border-radius: 3px;
        height: 25px;
        font-size: 15px;
        margin-right: 2px;
        color: white;
        display: flex;
        cursor: pointer;
        flex-direction: column;
        justify-content: center;
      }

      .tips-name {
        padding: 3px 5px;
        background: #409EFF;
        .tips-name-txt {
          white-space: nowrap;
        }
        :deep(.el-input) {
          min-width: 200px;
        }
      }

      .tips-copy {
        background: #67C23A;
        padding: 3px 8px;
      }

      .tips-tpl {
        background: #ff8000;
        padding: 3px 8px;
      }

      .tips-delete {
        background: #F56C6C;
        padding: 3px 8px;
      }
    }
    .tips-node {
      display: none;
      flex-direction: column;
      width: fit-content;
      .tips-node-item {
        white-space: nowrap;
        border-radius: 3px;
        margin-top: 1px;
        padding: 3px 5px;
        height: 25px;
        font-size: 15px;
        color: white;
        display: flex;
        cursor: pointer;
        flex-direction: column;
        justify-content: center;
        background: #409EFF;
      }
    }
  }
  .tips-box:has(.tips-name:hover) .tips-node, .tips-box .tips-node:hover{
    display: inline-flex;
  }
}
.mouseover-box {
  display: none;
  position: absolute;
  border: 1px solid #0085f6;
  box-sizing: border-box;
  pointer-events: none;
  .tips-box {
    position: relative;
    top: calc(100% + 3px);
    text-align: center;
    pointer-events: auto;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    width: 100%;
    color: rgb(33, 138, 246);
  }
}
.editor-page {
  width: 300px;
  box-sizing: border-box;
  overflow: auto;
  :deep(.el-collapse-item__header) {
    box-sizing: border-box;
  }
  .page-title {
    display: flex;
    flex-direction: row;
    margin: 0 10px;
    .page-title-name {
      flex-grow: 1;
    }
    .page-title-icon {
      margin: auto;
    }
  }
  .filter-box {
    margin: 0 10px 10px 10px;
  }
  .tree {
    :deep(.el-tree-node__content) {
      height: 40px;
    }
  }
  .node-item {
    display: flex;
    flex-direction: row;
    align-items: center;
    width: 100%;

    .node-label {
      margin-left: 10px;
      flex-grow: 1;
      width: 1px;
      text-overflow: ellipsis;
      overflow: hidden;
      display: flex;

      .item-name {
        width: 100%;
        text-overflow: ellipsis;
        overflow: hidden;
      }
    }
    .node-button {
      margin-right: 10px;
      display: flex;
      justify-content: center;
      align-items: center;
    }
    .node-button .node-button-item {
      width: 40px;
      display: flex;
      justify-content: center;
      align-items: center;
      border-radius: 5px;
    }
    .node-button .node-button-item:focus-visible {
      outline: unset;
    }
  }
}

</style>